<html>
<head>
  <style>
    li {
      list-style: none;
      float: left;
    }
    img {
      border: 0;  /*ie6*/
      vertical-align: middle;
    }
    p {
      width: 124px;
      font-size: 12px;
      color: #666;
      margin-left: 31px;
      overflow: hidden;
      /* text-overflow: ellipsis; */
      height: 33px;
    }
    #videoDiv {
      height: 231px;
    }
    #backPath {
        cursor: pointer;
        color: red;
    }
    #h1 {
        margin-top: 0px;
        margin-bottom: 10px;
        border-bottom: 1px solid #c0c0c0;
    }
    .up {
      background: url(" ") left top no-repeat
    }
    .icon {
      -webkit-padding-start: 1.5em;
      text-decoration: none;
      user-select: auto;
    }
    /* 黄色文件夹小图标 */
    /* .dir {
      background: url() left top no-repeat;
    } */
    /* 白色文件小图标 */
    /* .file {
      background: url() left top no-repeat;
    } */
    img {
      width: 150px;
      height: 100px;
    }
    .file .unknown {
      width: 100px;
    }
    .dir .unknown {
      width: 130px;
    }
    .down {
      margin-bottom: 10px;
      padding-bottom: 10px;
    }
    body {
      margin: 0;
      padding: 0;
    }
    .video {
      width: 150px;
      height: 100px;
    }
    video {
      width: 100%;
      height: 100%;
      display: none;
    }
  </style>

  <script>
    let setIntervalId = 0;
    async function playVideo(eve){
      eve.style.display = 'none';
      const video = eve.nextElementSibling;
      video.style.display = 'block';
      if(!video.className.includes('startPlay'))video.className += ' startPlay'
      await video.play()
      // 确保每次自增视频的4分之1
      const skip = Math.ceil(video.duration / 4);
      let times = 4;
      setIntervalId = setInterval(() => {
        console.log(skip, 'skip')
        // 如果播放到头，那么就从新分为4段开始播放，并且第一次不能计算skip，必须播完开头那几秒
        // 如果不return，那么会立刻跳转到视频的四分之一处
        if (video.currentTime === video.duration) {
          times = 4;
          video.currentTime = 0;
          video.play();
          return
        }
        // 到最后一段的时候不要直接跳转到视频结尾, 而是把最后一段分为几次播放
        if (times == 1) {
          video.currentTime = (video.currentTime + skip) - skip / 1.5;
          return
        }
        video.currentTime += skip;
        times--;
      }, 2000);
      console.log(setIntervalId, 'id')
    }

    function stopVideo(eve){
      if (!setIntervalId) return;
      clearInterval(setIntervalId);
      if (!eve) {
        const playingVideos = document.getElementsByClassName('startPlay');
        console.log(playingVideos)
        for (let video of playingVideos) {
          video.pause();
          video.style.display = 'none';
          video.previousElementSibling.style.display = 'block';
          video.className = video.className.replace(/ startPlay/g, '')
        }
        return;
      }
      eve.className = eve.className.replace(/ startPlay/g, '')
      eve.pause();
      eve.style.display = 'none';
      eve.previousElementSibling.style.display = 'block';
      setIntervalId = 0;
    }

    function getCurrentElement(event){
      // 通过event里的x，y  获取到页面上的元素并返回
      const x = event.clientX, y = event.clientY,
      element = document.elementFromPoint(x, y);
      return element
    }

    function trackMouse(event){
      // 通过 window.onmousemove 事件给的event调用getCurrentElement
      // elementMouseIsOver就是返回的元素，如果鼠标当前指向的元素类名不包含 real_video 说明它不是video标签，则调用stopVideo
      const elementMouseIsOver = getCurrentElement(event);
      if (!elementMouseIsOver) return;
      if (!elementMouseIsOver.className.includes('real_video')) stopVideo()
    }
    // 主要是解决video标签的onmouseleave事件没有触发问题，当鼠标移动过快，事件就没有触发，视频还在播放
    window.onmousemove = trackMouse;
  </script>

  <script>
    const viewList = {};
    let name = '';
    function pressEnter(ele, eve){
      if (eve.keyCode === 13) ready(ele.value)
    };

    // 当鼠标移到带有标题的p标签时会调用该函数，先把name等于标签里的内容，然后判断显示移除还是到上限
    // 鼠标移走的时候把p标签内容还原为标题，name清空。
    // remove的时候因为鼠标滑过p标签触发addToListButton直接取到name
    // 安卓默认显示添加到列表按钮，所以需要特殊判断，通过向上查找获取标题
    function addToListButton(ele){
      if (name) return;
      if (ele.id == 'android') {
        const parentNode = ele.parentNode;
        name = ele.previousSibling.previousSibling.innerText
        addToListFn(ele.previousSibling.previousSibling.firstChild);
        parentNode.removeChild(ele);
        parentNode.innerHTML += `<button type="button" onclick="removeToListFn(this)" id="android">从观看列表移除</button>`;
        return;
      }
      name = ele.innerText.split('/');
      name = name[name.length - 1]
      if (viewList[name]) {
        ele.innerHTML = `<button type="button" onclick="removeToListFn(this)">从观看列表移除</button>`;
        return;
      }
      // 9个是最优的展示效果
      if (Object.keys(viewList).length >= 9) {
        ele.innerText = `已达到上限`;
        return;
      }
      ele.innerHTML = `<button type="button" onclick="addToListFn(this)">添加到观看列表</button>`;
    };

    function removeToList(ele){
      ele.innerText = name;
      name = '';
    };

    function addToListFn(ele){
      const parentNode = ele.parentNode;
      viewList[name] = parentNode.previousSibling.previousSibling.href;
      // 浏览器规定同域名的并发请求最多7个，超过7个需要换域名，改为5个就换是为了让服务器的两个端口进程达到负载均衡效果，
      if (Object.keys(viewList).length >= 5) {
        viewList[name] = parentNode.previousSibling.previousSibling.href.replace('3001', '3002');
      }
      localStorage.setItem('viewList', JSON.stringify(viewList))
      document.getElementById('viewList').innerHTML = Object.keys(viewList).join('<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button><br/><br/>') + `<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button>`;
      if (android) {
        name = '';
        $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
        return;
      }
      $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
      parentNode.innerHTML = `<button type="button" onclick="removeToListFn(this)">从观看列表移除</button>`;
    };

    function clearPlayList(){
      for (let item in viewList) {
        delete viewList[item]
      }
      $("#viewList")[0].innerHTML = ''
      localStorage.setItem('viewList', '{}')
    }

    function remove(ele){
      delete viewList[ele.previousSibling.textContent];
      const videoLen = Object.keys(viewList).length;
      localStorage.setItem('viewList', JSON.stringify(viewList))
      document.getElementById('viewList').innerHTML = Object.keys(viewList).join('<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button><br/><br/>') + `${videoLen ? `<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button>` : ''}`
      if (videoLen != 0) $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
    }

    function removeToListFn(ele){
      if (!name) {
        const parentNode = ele.parentNode;
        name = ele.previousSibling.previousSibling.innerText
      }
      delete viewList[name];
      localStorage.setItem('viewList', JSON.stringify(viewList))
      document.getElementById('viewList').innerHTML = Object.keys(viewList).join('<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button><br/><br/>') + `<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button>`
      if (Object.keys(viewList).length != 0) $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
      const parentNode = ele.parentNode;
      if (ele.id == 'android') {
        parentNode.removeChild(ele);
        parentNode.innerHTML += `<button type="button" onclick="addToListButton(this)" id="android">添加到观看列表</button>`;
        name = ''
        return
      }
      parentNode.innerHTML = `<button type="button" onclick="addToListFn(this)">添加到观看列表</button>`;
    };

    function generateTag(){
      let tag = '';
      for (let url of Object.values(viewList)) {
        tag += `<video controls="controls" muted="muted" src='${url}' class="generateVideo" style="width: px; height: px;">
                  your browser does not support the video tag
                </video>`
      }
      localStorage.setItem('videos', tag);
      window.location.href = `${domain}test.html`
    };

    function playAll(){
      console.log(document.documentElement.clientHeight, document.documentElement.clientWidth);
      console.log(generateTag());
      document.getElementById('bb').innerHTML = `${generateTag()}`;
    };
  </script>

  <script src="./javascripts/jquery.min.js"></script>

  <script>
    const domain = `${window.location.origin}/`;
    // 最上面的路径是一个h1标签和h1里无数个span，h1标签也有自己的onclick，span有自己的onclick。
    // h1标签展示的永远是public，span展示的是每一级路径
    // 当点击非public路径时(也就是span标签)，也会触发h1的onclick(冒泡)。
    // 当点击h1时，不会触发span的onclick
    // 所以需要bubble变量来控制
    let bubble = false
    // 存在cookie里的路径，防止刷新后返回主目录
    let cachePath = '/'
    let videoToImgPath = {}
    const imgType = ['jpg', 'jpeg', 'png'];
    const videoType = ['mp4', 'avi', 'mkv', "rmvb"];
    function findCookie(cookie){
      for (let item of document.cookie.split(';')) {
        const key = item.split('=')
        // 正则为去除字符串前后空格，被split的cookie可能是["name=liu", " path=wer/VRVR-029"]，path前有空格导致key[0]不匹配
        if (key[0] && key[0].replace(/(^[\s\n\t]+|[\s\n\t]+$)/g, "") === cookie) {
          return key[1] || ''
        }
      }
      return ''
    }
    const android = !navigator.userAgent.includes('Windows') && !navigator.userAgent.includes('Mac');
    // const android = true;
    // 页面加载后触发
    const ready = async function (keyWords){
      console.log('cookie', document.cookie.split(';'), keyWords);
      console.log(`ws://${window.location.hostname}:36013${decodeURIComponent(findCookie('authId'))}`)
      await new Promise(function (resolve){
        const ws = new WebSocket(`ws://${window.location.hostname}:36013${decodeURIComponent(findCookie('authId'))}`);

        ws.onclose = function(evt) {
          console.log('onclose', evt);
        };

        ws.onopen = function() {
          console.log('onopen');
          resolve();
        };

        ws.onmessage = function(evt) {
          alert(evt.data)
        };

        ws.onerror = function(evt) {
          console.log('onerror', evt)
        };
      })
      if (document.cookie && document.cookie.split(';').length) {
        cachePath += `${findCookie('path')}`
      }
      const pathArr = cachePath.split('/').filter(item => item)
      console.log('cachePath', `${domain}?path=${cachePath}`);
      // 获取缩略图
      await new Promise(function (resolve, reject){
        $.get(`${domain}imgPath`, function(data, status){
          videoToImgPath = data;
          resolve();
          console.log(videoToImgPath)
        });
      })

      $.get(typeof keyWords == "string" ? `${domain}search?keyWords=${keyWords}` : `${domain}file/list?path=${cachePath}`, function(data, status){
        Object.assign(viewList, JSON.parse(localStorage.getItem('viewList')))
        if (Object.keys(viewList).length) {
          document.getElementById('viewList').innerHTML = Object.keys(viewList).join('<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button><br/><br/>') + `<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button>`;
          $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
        }
        if (cachePath != '/' && typeof keyWords != "string") {
          document.getElementById('previous').innerHTML = `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tips：上次看到这儿👇`
          document.getElementById('h1').innerHTML = `/public${cachePath.split('/').map(item => `<span onclick="backPathByClickEle(this.innerHTML, '${cachePath}')">${item}</span>` ).join('/')}`
          $("#bb").append(`
            <div class='down'>
              <a id='backPath' class="icon up" onclick="newfiles('${cachePath.replace(`/${pathArr[pathArr.length - 1]}`, '')}')">[上级目录]</a>
            </div>
        `)
        }
        if (typeof keyWords == "string") {
          $("#videoDiv").remove();
          $("#table").remove();
        }
        $("#bb").append(`
          <div id='videoDiv'>
            <ul id='table'></ul>
          </div>
        `)
        // 让文件夹在顶部，文件往下排
        data.sort((pre, next) => {
          if (pre.indexOf('.') == -1) {
            return -1
          }
          return 0
        })
        for (let i = 0; i < data.length; i++) {
          if (data[i].indexOf('.') != -1) {
            const splitFileName = data[i].split('.');
            const imgFile = imgType.includes(splitFileName[splitFileName.length - 1].toLowerCase());
            const videoFile = videoType.includes(splitFileName[splitFileName.length - 1].toLowerCase());
            $("#table").append(`
              <li>
                <a class="icon file" href='${domain}${typeof keyWords == "string" ? '' : cachePath === '/' ? '' : cachePath}/${data[i]}' >
                <div class="video">
                  <img src=${domain}/${encodeURI(`${imgFile ? (`${cachePath === '/' ? '' : cachePath}/${data[i]}`) : (typeof keyWords == "string" ? `${videoToImgPath[`${data[i]}`]}` : videoToImgPath[(cachePath === '/' ? '' : cachePath) + `/${data[i]}`] || 'thumbnails/unknown.png')}`)} class="${imgFile ? '' : videoToImgPath[(cachePath === '/' ? '' : cachePath) + `/${data[i]}`] ? '' : 'unknown'}" ${!videoFile ? '' : `onmousemove="playVideo(this)"`}>
                  <video preload="none" src='${domain}${keyWords ? '' : cachePath === '/' ? '' : cachePath}/${data[i]}' muted="muted" class="real_video" onmouseleave="stopVideo(this)">
                    your browser does not support the video tag
                  </video>
                </div>
              </a>
                <p ${!videoFile || imgFile ? '' : `onmousemove="addToListButton(this)" onmouseleave="removeToList(this)"`}>
                  ${data[i]}
                </p>
                ${imgFile ? '' : android ? viewList[data[i]] ? `<button type="button" onclick="removeToListFn(this)" id="android">从观看列表移除</button>` : `<button type="button" onclick="addToListButton(this)" id="android">添加到观看列表</button>` : ''}
              <li>`)
            } else {
              $("#table").append(`
                <li>
                  <a id="button" class="icon dir" style="cursor: pointer;color: #0000e8;" onclick="newfiles('${cachePath === '/' ? '' : cachePath}/${data[i]}')" >
                    <img src=${domain}/thumbnails/Movies.png  class='unknown'>
                    <p>
                      ${data[i]}
                    </p>
                  </a>
                <li>`)
            }
        }
      });
    };

    // 如果不用await，那ready函数返回的是一个 promise，网页什么也不显示
    !async function (){
      $(document).ready(await ready());
    }()
    

    function newfiles(params) {
      console.log('newfiles的params', params)
      $.get(`${domain}file/list?path=${params}`, function(data, status) {
        // "/qwe/"  split后就是["", "qwe", ""]  要想返回上一级目录而最后一个元素就是要被替换的
        const pathArr = params.split('/').filter(item => item)
        console.log('newfiles的pathArr', pathArr)
        // 如果是一级目录就不展示..了
        if (pathArr.length) {
          document.getElementById('bb').innerHTML=`
          <div id='viewList' style="right: 40px; top: 10px;position: fixed; color: brown; background-color: #fff;background-color: rgb(255, 255, 255, 0.9);"></div>
          <!-- 如果不join，那么返回的就是一个字符串数组，是以逗号分割，相当于自动被join(',') -->
          <h1 id='h1' onclick='goHome()'>/public/${pathArr.map(item => `<span onclick="backPathByClickEle(this.innerHTML, '${pathArr.join('/')}')">${item}</span>` ).join('/')}</h1>
          <div style="margin-top: -45px; margin-bottom: 30px;" align="center">
            <span style="margin-top: 2px;">搜索：&nbsp;</span>
            <input type="text" onkeypress="pressEnter(this, event)" />
            <span style="color: #5e5e69;">尝试搜索：凉森 破解|里美 39</span>
          </div>
          <div class='down'>
            <a id='backPath' class="icon up" onclick="newfiles('${params.replace(`/${pathArr[pathArr.length - 1]}`, '')}')" >[上级目录]</a>
          </div>
          <table id='table'></table>`
        } else {
          // 因为已经是一级目录了，没必要加onclick=goHome
          document.getElementById('bb').innerHTML=`
          <div id='viewList' style="right: 40px; top: 10px;position: fixed; color: brown; background-color: #fff;background-color: rgb(255, 255, 255, 0.9);"></div>
          <h1 id='h1' style="margin-bottom: 40px;">/public/</h1>
          <div style="margin-top: -75px; margin-bottom: 30px;" align="center">
            <span style="margin-top: 2px;">搜索：&nbsp;</span>
            <input type="text" onkeypress="pressEnter(this, event)" />
            <span style="color: #5e5e69;">尝试搜索：凉森 破解|里美 39</span>
          </div>
          <table id='table'></table>`
        }
        Object.assign(viewList, JSON.parse(localStorage.getItem('viewList')))
        if (Object.keys(viewList).length) {
          document.getElementById('viewList').innerHTML = Object.keys(viewList).join('<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button><br/><br/>') + `<button onclick="remove(this)" style="margin-left: 10px; width: 65px; height: 40px;">移除</button>`;
          $("#viewList").append(`<br><br><button onclick="playAll(this)" style="height: 38px; width: 140px; margin-bottom: 10px;" >开始播放所有</button><button onclick="clearPlayList(this)" style="margin-left: 20px;height: 38px; width: 140px; margin-bottom: 10px;" >清空</button>`)
        }
        // 让文件夹在顶部，文件往下排
        data.sort((pre, next) => {
          if (pre.indexOf('.') == -1) {
            return -1
          }
          return 0
        })
        for (let i = 0; i < data.length; i++) {
          if (data[i].indexOf('.') != -1) {
            const splitFileName = data[i].split('.');
            const imgFile = imgType.includes(splitFileName[splitFileName.length - 1].toLowerCase());
            const videoFile = videoType.includes(splitFileName[splitFileName.length - 1].toLowerCase());
            $("#table").append(`
              <li>
                <a class="icon file" href='${domain}/${params + '/' + data[i]}' >
                  <!-- 判断是不是图片文件，如果是的话，img标签的src直接取图片的路径，不是的话判断是不是一个视频文件，不是的话用unknown，class同理 -->
                <div class="video">
                  <img src=${domain}/${encodeURI(imgFile ? (params + '/' + data[i]) : (videoToImgPath[params + '/' + data[i]] || 'thumbnails/unknown.png'))} class="${imgFile ? '' : videoToImgPath[params + '/' + data[i]] ? '' : 'unknown'}" ${!videoFile ? '' : `onmousemove="playVideo(this)"`}>
                  <video preload="none" src='${domain}/${params + '/' + data[i]}' muted="muted" class="real_video" onmouseleave="stopVideo(this)">
                    your browser does not support the video tag
                  </video>
                </div>
              </a>
              <p ${!videoFile || imgFile ? '' : `onmousemove="addToListButton(this)" onmouseleave="removeToList(this)"`}>
                ${data[i]}
              </p>
              ${imgFile ? '' : android ? viewList[data[i]] ? `<button type="button" onclick="removeToListFn(this)" id="android">从观看列表移除</button>` : `<button type="button" onclick="addToListButton(this)" id="android">添加到观看列表</button>` : ''}
              <li>`)
          } else {
            $("#table").append(`
              <li>
                <a id="button" class="icon dir" style="cursor: pointer;color: #0000e8;" onclick="newfiles('${params + '/' + data[i]}')" >
                  <img src=${domain}/thumbnails/Movies.png class='unknown'}">
                  <p>
                    ${data[i]}
                  </p>
                </a>
              <li>`)
          }
        }
        const date = new Date;
        document.cookie = `path=${pathArr.join('/')};max-age=${60 * 60 * 24}`
      });
    }

    function backPathByClickEle(ele, pathArr){
      bubble = true
      const index = pathArr.indexOf(ele) + ele.length
      console.log(ele, pathArr, index, pathArr.substr(0, index))
      newfiles(pathArr.substr(0, index))
    }

    function goHome(){
      // 如果上面被触发，那么就会重置bubble的值，如果上面没被触发，就返回顶层目录
      bubble ? bubble = false : newfiles('')
    }
  </script>

</head>
  <body id="bb">
    <div id='viewList' style="right: 40px; top: 10px;position: fixed; color: brown; background-color: #fff;background-color: rgb(255, 255, 255, 0.9);"></div>
    <div id='previous' style="color:red"></div>
    <!-- 因为在61行直接修改的innerHTML，没法加onclick，而非108行直接写的h1标签 -->
    <h1 id='h1' onclick='goHome()'>/public/</h1>
    <div style="margin-top: -45px; margin-bottom: 30px;" align="center">
      <span style="margin-top: 2px;">搜索：&nbsp;</span>
      <input type="text" onkeypress="pressEnter(this, event)" />
      <span style="color: #5e5e69;">尝试搜索：凉森 破解|里美 39</span>
    </div>
  </body>
</html>

<script>
  !async function (){
    if (!android) {
      let notice = localStorage.getItem('notice');
      if ((parseInt(notice, 10) || 0) <= 0) {
        alert('\n建议按F11全屏浏览\n\n  1、将鼠标放到视频下方的文字上，添加到播放列表\n\n  2、最多选择九个视频\n\n  3、点击右上角开始播放\n\n  4、搜索时空格符表示并且，|表示或者')
        localStorage.setItem('notice', 10);
        return;
      }
      localStorage.setItem('notice', --notice)
    }
  }()
</script>